﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using UCL.Powersource;

namespace UCL.Powersource
{
    public interface IDisposableEx : IDisposable
    {

        bool IsDisposed { get; }
    }


    public interface IActivate
    {
        void Activate();
        bool IsActivated { get; }
        event EventHandler Activated;
    }

    public interface IDeactivate
    {
        void Deactivate();
        event EventHandler Deactivated;
    }

    public interface IInitialize
    {
        void Initialize();
        bool IsInitialized { get; }
    }

    public interface IInitialized
    {
        event EventHandler Initialized;
    }

    public interface IDisposed : IDisposableEx
    {
        event EventHandler Disposed;
    }
    public interface IGuardedDeactivate
    {
        bool TryDeactivate();
    }

    public interface IGuardedActivate
    {
        bool TryActivate();
    }

   

    public interface IActivationLifecycle : IInitiliazedLifeCycle, IActivate, IDeactivate, IInitialized, IDisposed { }
    
    public interface IInitiliazedLifeCycle : IInitialize, IDisposableEx { }
    [DataContract]
    public abstract class InitializedLifeCycleBase : IInitiliazedLifeCycle
    {

        private ILog _Log;
      
        public ILog Log 
        {
            get { return _Log ?? LogManager.GetLog(typeof(InitializedLifeCycleBase)); }
            protected set { _Log = value; } 
        }
        
        protected abstract bool OnInitializing();
        protected abstract void OnDisposing();

        

        private bool _IsInitialized;

        public bool IsInitialized
        {
            get { return _IsInitialized; }
            private set
            {
                if (_IsInitialized == value) return;
                else
                {
                    Debug.Assert(value, "IsInitialized should never be set to false!");
                    _IsInitialized = value;
                }
            }
        }
        
      

        private bool _IsDisposed;
        public bool IsDisposed
        {
            get { return _IsDisposed; }
            private set
            {
                if (_IsDisposed == value) return;
                else
                {
                    Debug.Assert(value, "IsDisposed should never be set to false. It has false as an initial value and once set to true itForFE cannot be set back to false!");
                    _IsDisposed = value;
                }
            }
        }

        public bool IsLoaded { get { return IsInitialized && !IsDisposed; } }

        public void Initialize()
        {
            if (IsInitialized) return;
            Log = LogManager.GetLog(this.GetType());
            if (!OnInitializing()) throw new InvalidOperationException(string.Format("{0} cannot be initialized", this.GetType().FullName));
            else { 
                IsInitialized = true; 
            }
        }
        


        protected void Dispose(bool disposing)
        {
            
            if (Log != null && !disposing) { Log.Warn("{0} disposed incorrectly", this.GetType().FullName); }

            if (disposing && !IsDisposed)
            {
                OnDisposing();
                if (Log!=null) Log.Trace("{0} disposed, supressing Finalize", this.GetType().FullName);
                Log = null;
                IsDisposed = true;
                GC.SuppressFinalize(this);
            }
        }

        ~InitializedLifeCycleBase()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
        }

    }
    


}